package com.rm.zeyou.service.impl;

import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rm.zeyou.constant.CommonConstants;
import com.rm.zeyou.constant.NumberConstants;
import com.rm.zeyou.constant.OrderConstants;
import com.rm.zeyou.constant.RedisConstants;
import com.rm.zeyou.entity.*;
import com.rm.zeyou.mapper.*;
import com.rm.zeyou.response.ApiRestResponse;
import com.rm.zeyou.service.TechnicianConsumeDetailService;
import com.rm.zeyou.service.UserItemOrderService;
import com.rm.zeyou.util.check.CheckEmptyUtil;
import com.rm.zeyou.util.redis.RedisUtil;
import com.rm.zeyou.vo.request.TechnicianWalletVo;
import com.rm.zeyou.vo.response.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 技师收入/支出表 服务实现类
 * </p>
 *
 * @author YanYang
 * @since 2025-03-12 15:55:09
 */
@Service
public class TechnicianConsumeDetailServiceImpl extends ServiceImpl<TechnicianConsumeDetailMapper, TechnicianConsumeDetail> implements TechnicianConsumeDetailService {
    @Resource
    private TechnicianConsumeDetailMapper technicianConsumeDetailMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private TechnicianItemOrderMapper technicianItemOrderMapper;
    @Resource
    private GradeConfigMapper gradeConfigMapper;
    @Resource
    private TechnicianMapper technicianMapper;
    @Resource
    private UserItemOrderMapper userItemOrderMapper;
    @Resource
    private UserItemOrderService userItemOrderService;


    @Override
    public ApiRestResponse<TechnicianStatisticsResponseVo> technicianStatistics(Technician technician) {
        TechnicianStatisticsResponseVo vo = new TechnicianStatisticsResponseVo();
        TechnicianPersonalCenterResponseVo total = technicianConsumeDetailMapper.selectTotalAmount(technician.getId());
        if (CheckEmptyUtil.isEmpty(total)) {
            total = new TechnicianPersonalCenterResponseVo();
            total.setServeCount(NumberConstants.ZERO_CONSTANTS);
            total.setTodayCarAmount(BigDecimal.ZERO);
            total.setTodayItemAmount(BigDecimal.ZERO);
            total.setTodayTransactionAmount(BigDecimal.ZERO);
        }
        vo.setTotalTurnover(total.getTodayTransactionAmount());
        vo.setTotalCarFareRevenue(total.getTodayCarAmount());
        vo.setTotalItemRevenue(total.getTodayItemAmount());
        //在线时长
        TechnicianOnlineTimeRedis technicianOnlineTimeRedisVo = JSONObject.parseObject(redisUtil.hget(RedisConstants.TECHNICIAN_ONLINE_TIME, technician.getId().toString()), TechnicianOnlineTimeRedis.class);
        if (CheckEmptyUtil.isEmpty(technicianOnlineTimeRedisVo)) {
            vo.setOnlineTime("0");
        } else {
            vo.setOnlineTime(DateUtil.formatBetween(technicianOnlineTimeRedisVo.getTotalOnlineTime(), BetweenFormatter.Level.HOUR));
        }
        //加钟率
        BigDecimal bellRate = calculateBellRate(technician.getId());
        vo.setAddBellRate(bellRate);
        GradeConfig grade = gradeConfigMapper.selectById(technician.getGradeId());
        vo.setNowGradeName(grade.getGradeName());
        TechnicianStatisticsResponseVo nextGrade = gradeConfigMapper.selectNextGrade(total.getTodayTransactionAmount());
        if (CheckEmptyUtil.isEmpty(nextGrade)) {
            vo.setNextGradeName("已达到最高等级");
            vo.setSubPrice(BigDecimal.ZERO);
            vo.setProgressBar(BigDecimal.valueOf(100));
            vo.setNextGrade(BigDecimal.ZERO);
        } else {
            vo.setNextGrade(nextGrade.getNextGrade());
            vo.setNextGradeName(nextGrade.getNextGradeName());
            vo.setSubPrice(nextGrade.getSubPrice());
            BigDecimal divide = total.getTodayTransactionAmount().divide(nextGrade.getNextGrade(), 2, RoundingMode.HALF_UP);
            vo.setProgressBar(divide.multiply(new BigDecimal(100)));
        }


        TechnicianPersonalCenterResponseVo today = technicianConsumeDetailMapper.selectAmountById(technician.getId(), NumberConstants.ONE_CONSTANTS);
        if (!CheckEmptyUtil.isEmpty(today)) {
            TechnicianStatisticsResponseVo.TodayRevenue todayRevenue = new TechnicianStatisticsResponseVo.TodayRevenue();
            todayRevenue.setTodayItemRevenue(today.getTodayItemAmount());
            todayRevenue.setTodayCarFareRevenue(today.getTodayCarAmount());
            todayRevenue.setTodayTurnover(today.getTodayTransactionAmount());
            todayRevenue.setTodayServerNum(today.getServeCount());
            vo.setTodayRevenue(todayRevenue);
        } else {
            TechnicianStatisticsResponseVo.TodayRevenue todayRevenue = new TechnicianStatisticsResponseVo.TodayRevenue();
            todayRevenue.setTodayItemRevenue(BigDecimal.ZERO);
            todayRevenue.setTodayCarFareRevenue(BigDecimal.ZERO);
            todayRevenue.setTodayTurnover(BigDecimal.ZERO);
            todayRevenue.setTodayServerNum(NumberConstants.ZERO_CONSTANTS);
            vo.setTodayRevenue(todayRevenue);
        }

        TechnicianPersonalCenterResponseVo yesterday = technicianConsumeDetailMapper.selectAmountById(technician.getId(), NumberConstants.TWO_CONSTANTS);
        if (!CheckEmptyUtil.isEmpty(yesterday)) {
            TechnicianStatisticsResponseVo.YesterdayRevenue yesterdayRevenue = new TechnicianStatisticsResponseVo.YesterdayRevenue();
            yesterdayRevenue.setYesterdayItemRevenue(yesterday.getTodayItemAmount());
            yesterdayRevenue.setYesterdayCarFareRevenue(yesterday.getTodayCarAmount());
            yesterdayRevenue.setYesterdayTurnover(yesterday.getTodayTransactionAmount());
            yesterdayRevenue.setYesterdayServerNum(yesterday.getServeCount());
            vo.setYesterdayRevenue(yesterdayRevenue);
        } else {
            TechnicianStatisticsResponseVo.YesterdayRevenue yesterdayRevenue = new TechnicianStatisticsResponseVo.YesterdayRevenue();
            yesterdayRevenue.setYesterdayItemRevenue(BigDecimal.ZERO);
            yesterdayRevenue.setYesterdayCarFareRevenue(BigDecimal.ZERO);
            yesterdayRevenue.setYesterdayTurnover(BigDecimal.ZERO);
            yesterdayRevenue.setYesterdayServerNum(NumberConstants.ZERO_CONSTANTS);
            vo.setYesterdayRevenue(yesterdayRevenue);
        }


        return ApiRestResponse.success(vo);
    }

    @Override
    public ApiRestResponse<TechnicianWalletResponseVo> technicianWallet(Technician technician, TechnicianWalletVo technicianWalletVo) {
        TechnicianWalletResponseVo baseVo = new TechnicianWalletResponseVo();

        // 收入金额
        BigDecimal addAmount = technicianConsumeDetailMapper.selectAddAmount(technician.getId(), NumberConstants.ONE_CONSTANTS);
        //已提现金额
        BigDecimal payoutAmount = technicianConsumeDetailMapper.selectPayoutAmount(technician.getId());
        //可提现金额
        baseVo.setWithdrawalAmount(addAmount.subtract(payoutAmount));
        //冻结金额
        BigDecimal freezeAmount = technicianConsumeDetailMapper.selectAddAmount(technician.getId(), NumberConstants.ZERO_CONSTANTS);
        baseVo.setFreezeAmount(freezeAmount);
        //接单量
        Integer orderVolume = technicianConsumeDetailMapper.selectOrderVolume(technician.getId());
        baseVo.setOrderVolume(orderVolume);
        if (technicianWalletVo.getType().equals(NumberConstants.ZERO_CONSTANTS)) {
            //资金明细
            List<OrderList> orderListVo = new ArrayList<>();
            PageHelper.startPage(technicianWalletVo.getPageNum(), technicianWalletVo.getPageSize());
            List<OrderList> orderLists = technicianConsumeDetailMapper.selectOrderList(technician.getId(), technicianWalletVo.getSubType());
            if (!CheckEmptyUtil.isEmpty(orderLists)) {
                PageInfo<OrderList> source = new PageInfo<>(orderLists);
                PageInfo<OrderList> target = new PageInfo<>();
                BeanUtils.copyProperties(source, target);
                for (OrderList orderList : source.getList()) {
                    OrderList order = new OrderList();
                    if (orderList.getConsumeType().equals(CommonConstants.CONSUMPTION_ADD)) {
                        order.setTotalPrice(orderList.getTotalPrice());
                        order.setOrderRemark("项目收入");
                    } else {
                        order.setTotalPrice(orderList.getPayoutPrice());
                        order.setOrderRemark("支出提现");
                    }
                    order.setConsumeType(orderList.getConsumeType());
                    order.setOrderNo(orderList.getOrderNo());
                    order.setCreateTime(orderList.getCreateTime());

                    orderListVo.add(order);
                }
                target.setList(orderListVo);
                baseVo.setOrderList(target);
            } else {
                baseVo.setOrderList(new PageInfo<OrderList>());
            }
        } else {
            //收入明细
            RevenueDetailsList detailsList = technicianConsumeDetailMapper.selectDetailsList(technician.getId(), technicianWalletVo.getSubType());
            detailsList.setRevenueDetailsOrderList(PageHelper.startPage(technicianWalletVo.getPageNum(), technicianWalletVo.getPageSize())
                    .doSelectPageInfo(() -> technicianConsumeDetailMapper.selectRevenueDetailsOrderList(technician.getId(), technicianWalletVo.getSubType())));
            baseVo.setRevenueDetailsList(detailsList);
        }
        return ApiRestResponse.success(baseVo);
    }

    @Transactional(rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRED)
    @Override
    public void updateTechnicianConsumeGrade(Technician technician) {
        try {
            // 查询技师总成交额
            TechnicianPersonalCenterResponseVo total = technicianConsumeDetailMapper.selectTotalAmount(technician.getId());
            if (CheckEmptyUtil.isEmpty(total)) {
                total = new TechnicianPersonalCenterResponseVo();
                total.setServeCount(NumberConstants.ZERO_CONSTANTS);
                total.setTodayCarAmount(BigDecimal.ZERO);
                total.setTodayItemAmount(BigDecimal.ZERO);
                total.setTodayTransactionAmount(BigDecimal.ZERO);
            }
            BigDecimal totalClinch = total.getTodayTransactionAmount();

            // 计算加钟率
            BigDecimal bellRate = calculateBellRate(technician.getId());

            // 查询下一分成等级 如果条件符合 升级 不符合 维持 如果下一等级为空 说明已到最高等级 无需升级
            GradeConfig nextGrade = gradeConfigMapper.selectById(technician.getGradeId() + 1);
            if (!CheckEmptyUtil.isEmpty(nextGrade)) {
                if (totalClinch.compareTo(nextGrade.getMiniTurnover()) >= 0
                        && bellRate.multiply(new BigDecimal(100)).compareTo(nextGrade.getContinuationRate()) >= 0) {
                    technician.setGradeId(nextGrade.getId());
                    technicianMapper.updateById(technician);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("更新技师消费等级失败", e);
        }
    }

    @Override
    public void updateTechnicianConsume() throws Exception {
        List<TechnicianConsumeDetail> consumeList = technicianConsumeDetailMapper.selectList(new LambdaQueryWrapper<TechnicianConsumeDetail>()
                .eq(TechnicianConsumeDetail::getPriceStatus, NumberConstants.ZERO_CONSTANTS)
                .eq(TechnicianConsumeDetail::getConsumeType, CommonConstants.CONSUMPTION_ADD));
        if (!CheckEmptyUtil.isEmpty(consumeList)) {
            for (TechnicianConsumeDetail technicianConsume : consumeList) {
                //if (new Date().compareTo(DateUtils.addDay(technicianConsume.getCreateTime(), 7)) >= 0) {
                if (new Date().after(DateUtil.offsetDay(technicianConsume.getCreateTime(), 7))) {
                    technicianConsume.setPriceStatus(NumberConstants.ONE_CONSTANTS);
                    int i = technicianConsumeDetailMapper.updateById(technicianConsume);
                    if (i > 0) {
                        //更新订单状态
                        UserItemOrder userItemOrder = userItemOrderMapper.selectOneByOrderNo(technicianConsume.getOrderNo());

                        //UserItemOrder userItemOrder = userItemOrderMapper.selectOne(new LambdaQueryWrapper<UserItemOrder>()
                        //        .eq(UserItemOrder::getOrderNo, technicianConsume.getOrderNo()));

                        userItemOrderService.userConfirmOrder(userItemOrder);


                    }
                }
            }
        }
    }

    private BigDecimal calculateBellRate(Long technicianId) {
        // 加钟订单数
        Integer bellOrderCount = technicianItemOrderMapper.selectBellOrderCount(technicianId);

        Integer normalOrderCount = 0;
        List<TechnicianItemOrder> technicianItemOrders = technicianItemOrderMapper.selectList(new LambdaQueryWrapper<TechnicianItemOrder>()
                .eq(TechnicianItemOrder::getTid, technicianId)
                .eq(TechnicianItemOrder::getOrderType, NumberConstants.ZERO_CONSTANTS)
                .in(TechnicianItemOrder::getOrderStatus, OrderConstants.ORDER_STATUS_PENDING_EVALUATION, OrderConstants.ORDER_STATUS_OVER)
        );
        if (!CheckEmptyUtil.isEmpty(technicianItemOrders)) {
            for (TechnicianItemOrder technicianItemOrder : technicianItemOrders) {
                int upgradeCount = technicianItemOrderMapper.selectCount(new LambdaQueryWrapper<TechnicianItemOrder>()
                        .eq(TechnicianItemOrder::getTid, technicianId)
                        .eq(TechnicianItemOrder::getOrderType, NumberConstants.TWO_CONSTANTS)
                        .eq(TechnicianItemOrder::getPartnerOrderNo, technicianItemOrder.getOrderNo())
                        .in(TechnicianItemOrder::getOrderStatus, OrderConstants.ORDER_STATUS_PENDING_EVALUATION, OrderConstants.ORDER_STATUS_OVER)
                ).intValue();
                normalOrderCount += (upgradeCount == 0) ? 1 : upgradeCount;
            }
        }
        return (bellOrderCount == 0 || normalOrderCount == 0) ? BigDecimal.ZERO
                : new BigDecimal(bellOrderCount).divide(new BigDecimal(normalOrderCount), 2, RoundingMode.HALF_UP);
    }

}
